/*
 * Copyright (c) 2022, IMMORTA Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * - Neither the name of IMMORTA Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ADC_REG_ACCESS_H
#define ADC_REG_ACCESS_H

/*!
 * @file adc_reg_access.h
 * @brief This file declares or defines adc register access functions
 */

/*******Includes***************************************************************/
#include "adc_drv.h"

/*******Definitions************************************************************/
/*! @brief All end of sequence conversion flag mask */
#define ADC_SR0_ALL_EOS_Msk      (0x6UL)

/*! @brief All end of channel conversion flag mask for priority channel */
#define ADC_SR0_ALL_PEOC_Msk     (0xF00UL)

/*! @brief All analog watchdog event flag mask for priority channel */
#define ADC_SR0_ALL_PAWD_Msk     (0xF000UL)

/*! @brief ADC buffer select position */
#define ADC_BUFFER_SEL_Pos       (0x1UL)

/*******APIs*******************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @brief Get the adc idle status
 *
 * @param[in] regBase: The adc register base address
 * @return Idle status
 *         - true: ADC is idle
 *         - false: ADC is busy
 */
static inline bool ADC_REG_GetIdleStatus(ADC_Type* regBase)
{
    uint32_t regValue = 0U;

    regValue = (regBase->SR0 & ADC_SR0_IDLE_Msk) >> ADC_SR0_IDLE_Pos;

    return (bool)regValue;
}

/*!
 * @brief Get the adc end of priority channel sequence conversion status
 *
 * @param[in] regBase: The adc register base address
 * @return PEOS flag
 *         - true: Sequence conversion is complete
 *         - false: Sequence conversion is not complete
 */
static inline bool ADC_REG_GetPEOSFlag(ADC_Type* regBase)
{
    uint32_t regValue = 0U;

    regValue = (regBase->SR0 & ADC_SR0_PEOS_Msk) >> ADC_SR0_PEOS_Pos;

    return (bool)regValue;
}

/*!
 * @brief Clear the adc end of priority channel sequence conversion status
 *
 * @param[in] regBase: The adc register base address
 * @return None
 */
static inline void ADC_REG_ClrPEOSFlag(ADC_Type* regBase)
{
    regBase->SR0 = ADC_SR0_PEOS_Msk;
}

/*!
 * @brief Get the adc end of normal channel sequence conversion status
 *
 * @param[in] regBase: The adc register base address
 * @return NEOS flag
 *         - true: Sequence conversion is complete
 *         - false: Sequence conversion is not complete
 */
static inline bool ADC_REG_GetNEOSFlag(ADC_Type* regBase)
{
    uint32_t regValue = 0U;

    regValue = (regBase->SR0 & ADC_SR0_NEOS_Msk) >> ADC_SR0_NEOS_Pos;

    return (bool)regValue;
}

/*!
 * @brief Clear the adc end of normal channel sequence conversion status
 *
 * @param[in] regBase: The adc register base address
 * @return None
 */
static inline void ADC_REG_ClrNEOSFlag(ADC_Type* regBase)
{
    regBase->SR0 = ADC_SR0_NEOS_Msk;
}

/*!
 * @brief Get All end of sequence conversion status for normal channel and priority channel
 *
 * @param[in] regBase: The adc register base address
 * @return All EOS flag
 */
static inline uint8_t ADC_REG_GetAllEOSFlag(ADC_Type* regBase)
{
    uint32_t regValue = 0U;

    regValue = (regBase->SR0 & ADC_SR0_ALL_EOS_Msk) >> ADC_SR0_PEOS_Pos;

    return (uint8_t)regValue;
}

/*!
 * @brief Clear All end of sequence conversion status for normal channel and priority channel
 *
 * @param[in] regBase: The adc register base address
 * @param[in] eosMsk: End of sequence conversion status mask
 * @return None
 */
static inline void ADC_REG_ClrAllEOSFlag(ADC_Type* regBase, uint8_t eosMsk)
{
    regBase->SR0 = (((uint32_t)eosMsk << ADC_SR0_PEOS_Pos) & ADC_SR0_ALL_EOS_Msk);
}

/*!
 * @brief Get all end of priority channel conversion status
 *
 * @param[in] regBase: The adc register base address
 * @return PEOC flag
 */
static inline uint8_t ADC_REG_GetAllPEOCFlag(ADC_Type* regBase)
{
    uint32_t regValue = 0U;

    regValue = (regBase->SR0 & ADC_SR0_ALL_PEOC_Msk) >> ADC_SR0_PEOC0_Pos;

    return (uint8_t)regValue;
}

/*!
 * @brief Clear all end of priority channel conversion status
 *
 * @param[in] regBase: The adc register base address
 * @param[in] peocMsk: End of channel conversion status mask
 * @return None
 */
static inline void ADC_REG_ClrAllPEOCFlag(ADC_Type* regBase, uint8_t peocMsk)
{
    regBase->SR0 = (((uint32_t)peocMsk << ADC_SR0_PEOC0_Pos) & ADC_SR0_ALL_PEOC_Msk);
}

/*!
 * @brief Get all analog watchdog event flag for priority channel
 *
 * @param[in] regBase: The adc register base address
 * @return Analog watchdog event flag
 */
static inline uint8_t ADC_REG_GetAllPAwdFlag(ADC_Type* regBase)
{
    uint32_t regValue = 0U;

    regValue = (regBase->SR0 & ADC_SR0_ALL_PAWD_Msk) >> ADC_SR0_PAWD0_Pos;

    return (uint8_t)regValue;
}

/*!
 * @brief Clear all analog watchdog event flag for priority channel
 *
 * @param[in] regBase: The adc register base address
 * @param[in] pawdMsk: Analog watchdog event flag mask
 * @return None
 */
static inline void ADC_REG_ClrAllPAwdFlag(ADC_Type* regBase, uint8_t pawdMsk)
{
    regBase->SR0 = (((uint32_t)pawdMsk << ADC_SR0_PAWD0_Pos) & ADC_SR0_ALL_PAWD_Msk);
}

/*!
 * @brief Get all end of channel conversion status for normal channel
 *
 * @param[in] regBase: The adc register base address
 * @return NEOC flag
 */
static inline uint32_t ADC_REG_GetAllNEOCFlag(ADC_Type* regBase)
{
    return regBase->SR1;
}

/*!
 * @brief Clear all end of normal channel conversion status
 *
 * @param[in] regBase: The adc register base address
 * @param[in] neocMsk: End of channel conversion status mask
 * @return None
 */
static inline void ADC_REG_ClrAllNEOCFlag(ADC_Type* regBase, uint32_t neocMsk)
{
    regBase->SR1 = neocMsk;
}

/*!
 * @brief Get all analog watchdog event flag for normal channel
 *
 * @param[in] regBase: The adc register base address
 * @return Analog watchdog event flag
 */
static inline uint32_t ADC_REG_GetAllNAwdFlag(ADC_Type* regBase)
{
    return regBase->SR2;
}

/*!
 * @brief Clear all analog watchdog event flag for normal channel
 *
 * @param[in] regBase: The adc register base address
 * @param[in] nawdMsk: Analog watchdog event flag mask
 * @return None
 */
static inline void ADC_REG_ClrAllNAwdFlag(ADC_Type* regBase, uint32_t nawdMsk)
{
    regBase->SR2 = nawdMsk;
}

/*!
 * @brief Enable/Disable adc module
 *
 * @param[in] regBase: The adc register base address
 * @param[in] enable
 *            - true: Enable adc
 *            - false: Disable adc
 * @return None
 */
static inline void ADC_REG_SetADCEn(ADC_Type* regBase, bool enable)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_ADON_Msk)
                   | ((uint32_t)enable << ADC_CR0_ADON_Pos);
}

/*!
 * @brief Set adc priority channel trigger mode
 *
 * @param[in] regBase: The adc register base address
 * @param[in] mode
 *            - 0: ADC_SOFTWARE_TRIGGER
 *            - 1: ADC_HARDWARE_TRIGGER
 * @return None
 */
static inline void ADC_REG_SetPriorityChTriggerMode(ADC_Type* regBase, adc_trigger_type_t mode)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_PEXTTRIG_Msk)
                   | ((uint32_t)mode << ADC_CR0_PEXTTRIG_Pos);
}

/*!
 * @brief Set adc software trigger for priority channel
 *
 * @param[in] regBase: The adc register base address
 * @return None
 */
static inline void ADC_REG_SetPriorityChSoftwareTrigger(ADC_Type* regBase)
{
    regBase->CR0 |= ADC_CR0_PSWSTART_Msk;
}

/*!
 * @brief Set adc normal channel trigger mode
 *
 * @param[in] regBase: The adc register base address
 * @param[in] mode
 *            - 0: ADC_SOFTWARE_TRIGGER
 *            - 1: ADC_HARDWARE_TRIGGER
 * @return None
 */
static inline void ADC_REG_SetNormalChTriggerMode(ADC_Type* regBase, adc_trigger_type_t mode)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_NEXTTRIG_Msk)
                   | ((uint32_t)mode << ADC_CR0_NEXTTRIG_Pos);
}

/*!
 * @brief Set adc software trigger for normal channel
 *
 * @param[in] regBase: The adc register base address
 * @return None
 */
static inline void ADC_REG_SetNormalChSoftwareTrigger(ADC_Type* regBase)
{
    regBase->CR0 |= ADC_CR0_NSWSTART_Msk;
}

/*!
 * @brief Set adc dma mode
 *
 * @param[in] regBase: The adc register base address
 * @param[in] mode
 *            - 0: ADC_DMA_DISABLE
 *            - 1: ADC_NORMAL_CHANNEL_DMA_ENABLE
 *            - 2: ADC_PRIORITY_CHANNEL_DMA_ENABLE
 * @return None
 */
static inline void ADC_REG_SetDMAMode(ADC_Type* regBase, adc_dma_mode_t mode)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_DMAMODE_Msk)
                   | ((uint32_t)mode << ADC_CR0_DMAMODE_Pos);
}

/*!
 * @brief Set adc hardware average times
 *
 * @param[in] regBase: The adc register base address
 * @param[in] times
 *            - 0: ADC_AVERAGE_4
 *            - 1: ADC_AVERAGE_8
 *            - 2: ADC_AVERAGE_16
 *            - 3: ADC_AVERAGE_32
 * @return None
 */
static inline void ADC_REG_SetAverageTimes(ADC_Type* regBase, adc_average_t times)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_AVGS_Msk)
                   | ((uint32_t)times << ADC_CR0_AVGS_Pos);
}

/*!
 * @brief Enable/Disable adc hardware average
 *
 * @param[in] regBase: The adc register base address
 * @param[in] enable
 *            - true: Enable hardware average
 *            - false: Disable hardware average
 * @return None
 */
static inline void ADC_REG_SetAverageEn(ADC_Type* regBase, bool enable)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_AVGE_Msk)
                   | ((uint32_t)enable << ADC_CR0_AVGE_Pos);
}

/*!
 * @brief Enable/Disable adc calibration
 *
 * @param[in] regBase: The adc register base address
 * @param[in] enable
 *            - true: Enable calibration
 *            - false: Disable calibration
 * @return None
 */
static inline void ADC_REG_SetCalibrationEn(ADC_Type* regBase, bool enable)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_CALE_Msk)
                   | ((uint32_t)enable << ADC_CR0_CALE_Pos);
}

/*!
 * @brief Stop current adc conversion
 *
 * @param[in] regBase: The adc register base address
 * @return None
 */
static inline void ADC_REG_StopConversion(ADC_Type* regBase)
{
    regBase->CR0 |= ADC_CR0_SWSTOP_Msk;
}

/*!
 * @brief Set priority channel conversion mode
 *
 * @param[in] regBase: The adc register base address
 * @param[in] mode
 *            - 0: ADC_SINGLE_MODE
 *            - 1: ADC_SCAN_MODE
 *            - 2: ADC_CONTINOUS_MODE
 * @return None
 */
static inline void ADC_REG_SetPriorityChMode(ADC_Type* regBase, adc_conversion_mode_t mode)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_PMODE_Msk)
                   | ((uint32_t)mode << ADC_CR0_PMODE_Pos);
}

/*!
 * @brief Set normal channel conversion mode
 *
 * @param[in] regBase: The adc register base address
 * @param[in] mode
 *            - 0: ADC_SINGLE_MODE
 *            - 1: ADC_SCAN_MODE
 *            - 2: ADC_CONTINOUS_MODE
 * @return None
 */
static inline void ADC_REG_SetNormalChMode(ADC_Type* regBase, adc_conversion_mode_t mode)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_NMODE_Msk)
                   | ((uint32_t)mode << ADC_CR0_NMODE_Pos);
}

/*!
 * @brief Set priority channel sequence length
 *
 * @param[in] regBase: The adc register base address
 * @param[in] len: Sequence length
 * @return None
 */
static inline void ADC_REG_SetPriorityChSequenceLen(ADC_Type* regBase, uint8_t len)
{
    uint32_t regValue = 0U;

    regValue = regBase->CR0 & ~ADC_CR0_PSQL_Msk;
    regValue |= ((uint32_t)len << ADC_CR0_PSQL_Pos) & ADC_CR0_PSQL_Msk;
    regBase->CR0 = regValue;
}

/*!
 * @brief Set normal channel sequence length
 *
 * @param[in] regBase: The adc register base address
 * @param[in] len: Sequence length
 * @return None
 */
static inline void ADC_REG_SetNormalChSequenceLen(ADC_Type* regBase, uint8_t len)
{
    uint32_t regValue = 0U;

    regValue = regBase->CR0 & ~ADC_CR0_NSQL_Msk;
    regValue |= ((uint32_t)len << ADC_CR0_NSQL_Pos) & ADC_CR0_NSQL_Msk;
    regBase->CR0 = regValue;
}

/*!
 * @brief Set adc data conversion
 *
 * @param[in] regBase: The adc register base address
 * @param[in] resolution
 *            - 0: ADC_RESOLUTION_12BIT
 *            - 1: ADC_RESOLUTION_10BIT
 *            - 2: ADC_RESOLUTION_8BIT
 * @return None
 */
static inline void ADC_REG_SetDataResolution(ADC_Type* regBase, adc_resolution_t resolution)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_RES_Msk)
                   | ((uint32_t)resolution << ADC_CR0_RES_Pos);
}

/*!
 * @brief Set adc positive reference voltage
 *
 * @param[in] regBase: The adc register base address
 * @param[in] resolution
 *            - 0: ADC_VDDA
 *            - 1: ADC_EXTERNAL_VREFH
 * @return None
 */
static inline void ADC_REG_SetVrefP(ADC_Type* regBase, adc_vrefp_t ref)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_VREFPSEL_Msk)
                   | ((uint32_t)ref << ADC_CR0_VREFPSEL_Pos);
}

#if (CONFIG_ADC_SUPPORT_VREFL == 1U)
/*!
 * @brief Set adc negative reference voltage
 *
 * @param[in] regBase: The adc register base address
 * @param[in] resolution
 *            - 0: ADC_GND
 *            - 1: ADC_EXTERNAL_VREFL
 * @return None
 */
static inline void ADC_REG_SetVrefN(ADC_Type* regBase, adc_vrefn_t ref)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_VREFNSEL_Msk)
                   | ((uint32_t)ref << ADC_CR0_VREFNSEL_Pos);
}
#endif

/*!
 * @brief Enable/Disable adc pority channel end of sequence conversion interrupt
 *
 * @param[in] regBase: The adc register base address
 * @param[in] enable
 *            - true: Enable pority channel end of sequence conversion interrupt
 *            - false: Disable pority channel end of sequence conversion interrupt
 * @return None
 */
static inline void ADC_REG_SetPEOSIntEn(ADC_Type* regBase, bool enable)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_PEOSIE_Msk)
                   | ((uint32_t)enable << ADC_CR0_PEOSIE_Pos);
}

/*!
 * @brief Enable/Disable adc normal channel end of sequence conversion interrupt
 *
 * @param[in] regBase: The adc register base address
 * @param[in] enable
 *            - true: Enable normal channel end of sequence conversion interrupt
 *            - false: Disable normal channel end of sequence conversion interrupt
 * @return None
 */
static inline void ADC_REG_SetNEOSIntEn(ADC_Type* regBase, bool enable)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_NEOSIE_Msk)
                   | ((uint32_t)enable << ADC_CR0_NEOSIE_Pos);
}

/*!
 * @brief Enable/Disable adc buffer for bandgap or tensor, this function only valid for adc0
 *
 * @param[in] regBase: The adc register base address
 * @param[in] enable
 *            - true: Enable bandgap or tensor buffer for adc
 *            - false: Disable bandgap or tensor buffer for adc
 * @return None
 */
static inline void ADC_REG_SetBufferEn(ADC_Type* regBase, bool enable)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_BUFEN_Msk)
                   | ((uint32_t)enable << ADC_CR0_BUFEN_Pos);
}

/*!
 * @brief ADC buffer select for bandgap or tensor
 *
 * @param[in] regBase: The adc register base address
 * @param[in] adc_buffer_sel_t
 *            - ADC_BUFFER_DISABLE: Buffer disable
 *            - ADC_BUFFER_BANDGAP: Buffer select bandgap
 *            - ADC_BUFFER_TSENSOR: Buffer select tsensor
 * @return None
 */
static inline void ADC_REG_BufferSel(ADC_Type* regBase, adc_buffer_sel_t bufferSel)
{
    regBase->CR0 = (regBase->CR0 & ~ADC_CR0_BUFSEL_Msk)
                   | (((uint32_t)bufferSel >> ADC_BUFFER_SEL_Pos) << ADC_CR0_BUFSEL_Pos);
}

/*!
 * @brief Set the adc priority channel offset value
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @param[in] offset: Priority channel offset value
 * @return None
 */
static inline void ADC_REG_SetPriorityChOffsetVal(ADC_Type* regBase, adc_priority_channel_t channel, uint16_t offset)
{
    regBase->POFR[channel] = (regBase->POFR[channel] & ~ADC_POFR0_POFFSET_Msk)
                             | ((uint32_t)offset << ADC_POFR0_POFFSET_Pos);
}

/*!
 * @brief Set the analog watchdog high threshold
 *
 * @param[in] regBase: The adc register base address
 * @param[in] awdCh: Analog watchdog channel
 * @param[in] threshold: Analog watchdog high threshold
 * @return None
 */
static inline void ADC_REG_SetAwdHighThreshold(ADC_Type* regBase, adc_analog_watchdog_t awdCh, uint16_t threshold)
{
    regBase->AWD[awdCh].HTR = (regBase->AWD[awdCh].HTR & ~ADC_HTR0_AWDHT_Msk)
                              | ((uint32_t)threshold << ADC_HTR0_AWDHT_Pos);
}

/*!
 * @brief Set the analog watchdog low threshold
 *
 * @param[in] regBase: The adc register base address
 * @param[in] awdCh: Analog watchdog channel
 * @param[in] threshold: Analog watchdog low threshold
 * @return None
 */
static inline void ADC_REG_SetAwdLowThreshold(ADC_Type* regBase, adc_analog_watchdog_t awdCh, uint16_t threshold)
{
    regBase->AWD[awdCh].LTR = (regBase->AWD[awdCh].LTR & ~ADC_LTR0_AWDLT_Msk)
                              | ((uint32_t)threshold << ADC_LTR0_AWDLT_Pos);
}

/*!
 * @brief Set the adc normal channel input select
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] input: ADC input select about internal channel and external channel
 * @return None
 */
static inline void ADC_REG_SetNormalChInputSel(ADC_Type* regBase, adc_normal_channel_t channel, adc_input_channel_t input)
{
    regBase->NSQR[channel] = (regBase->NSQR[channel] & ~ADC_NSQR0_CHSEL_Msk)
                             | ((uint32_t)input << ADC_NSQR0_CHSEL_Pos);
}

/*!
 * @brief Set the adc normal channel sample time
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] sampleTime: ADC sample time
 * @return None
 */
static inline void ADC_REG_SetNormalChSampleTime(ADC_Type* regBase, adc_normal_channel_t channel, adc_sample_time_t sampleTime)
{
    regBase->NSQR[channel] = (regBase->NSQR[channel] & ~ADC_NSQR0_SMP_Msk)
                             | ((uint32_t)sampleTime << ADC_NSQR0_SMP_Pos);
}

/*!
 * @brief Set the adc normal channel analog watchdog select
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] awd: Analog watchdog channel
 * @return None
 */
static inline void ADC_REG_SetNormalChAwdSel(ADC_Type* regBase, adc_normal_channel_t channel, adc_analog_watchdog_t awd)
{
    regBase->NSQR[channel] = (regBase->NSQR[channel] & ~ADC_NSQR0_AWDSEL_Msk)
                             | ((uint32_t)awd << ADC_NSQR0_AWDSEL_Pos);
}

/*!
 * @brief Enable/Disable adc normal channel analog watchdog
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] enable
 *            - true: Enable analog watchdog for normal channel
 *            - false: Disable analog watchdog for normal channel
 * @return None
 */
static inline void ADC_REG_SetNormalChAwdEn(ADC_Type* regBase, adc_normal_channel_t channel, bool enable)
{
    regBase->NSQR[channel] = (regBase->NSQR[channel] & ~ADC_NSQR0_AWDEN_Msk)
                             | ((uint32_t)enable << ADC_NSQR0_AWDEN_Pos);
}

/*!
 * @brief Enable/Disable adc normal channel analog watchdog event interrupt
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] enable
 *            - true: Enable analog watchdog event interrupt for normal channel
 *            - false: Disable analog watchdog event interrupt for normal channel
 * @return None
 */
static inline void ADC_REG_SetNormalChAwdIntEn(ADC_Type* regBase, adc_normal_channel_t channel, bool enable)
{
    regBase->NSQR[channel] = (regBase->NSQR[channel] & ~ADC_NSQR0_AWDIE_Msk)
                             | ((uint32_t)enable << ADC_NSQR0_AWDIE_Pos);
}

/*!
 * @brief Enable/Disable adc end of normal channel conversion interrupt
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] enable
 *            - true: Enable adc end of normal channel conversion interrupt
 *            - false: Disable adc end of normal channel conversion interrupt
 * @return None
 */
static inline void ADC_REG_SetNormalChEOCIntEn(ADC_Type* regBase, adc_normal_channel_t channel, bool enable)
{
    regBase->NSQR[channel] = (regBase->NSQR[channel] & ~ADC_NSQR0_EOCIE_Msk)
                             | ((uint32_t)enable << ADC_NSQR0_EOCIE_Pos);
}

/*!
 * @brief Enable/Disable adc normal channel analog watchdog trigger out to ICM
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] enable
 *            - true: Enable adc normal channel analog watchdog trigger out to ICM
 *            - false: Disable adc normal channel analog watchdog trigger out to ICM
 * @return None
 */
static inline void ADC_REG_SetNormalChAwdTrigEn(ADC_Type* regBase, adc_normal_channel_t channel, bool enable)
{
    regBase->NSQR[channel] = (regBase->NSQR[channel] & ~ADC_NSQR0_AWDTRIGEN_Msk)
                             | ((uint32_t)enable << ADC_NSQR0_AWDTRIGEN_Pos);
}

/*!
 * @brief Set the adc priority channel input select
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @param[in] input: ADC input select about internal channel and external channel
 * @return None
 */
static inline void ADC_REG_SetPriorityChInputSel(ADC_Type* regBase, adc_priority_channel_t channel, adc_input_channel_t input)
{
    regBase->PSQR[channel] = (regBase->PSQR[channel] & ~ADC_PSQR0_CHSEL_Msk)
                             | ((uint32_t)input << ADC_PSQR0_CHSEL_Pos);
}

/*!
 * @brief Set the adc priority channel sample time
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @param[in] sampleTime: ADC sample time
 * @return None
 */
static inline void ADC_REG_SetPriorityChSampleTime(ADC_Type* regBase, adc_priority_channel_t channel, adc_sample_time_t sampleTime)
{
    regBase->PSQR[channel] = (regBase->PSQR[channel] & ~ADC_PSQR0_SMP_Msk)
                             | ((uint32_t)sampleTime << ADC_PSQR0_SMP_Pos);
}

/*!
 * @brief Set the adc priority channel analog watchdog select
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @param[in] awd: Analog watchdog channel
 * @return None
 */
static inline void ADC_REG_SetPriorityChAwdSel(ADC_Type* regBase, adc_priority_channel_t channel, adc_analog_watchdog_t awd)
{
    regBase->PSQR[channel] = (regBase->PSQR[channel] & ~ADC_PSQR0_AWDSEL_Msk)
                             | ((uint32_t)awd << ADC_PSQR0_AWDSEL_Pos);
}

/*!
 * @brief Enable/Disable adc priority channel analog watchdog
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @param[in] enable
 *            - true: Enable analog watchdog for priority channel
 *            - false: Disable analog watchdog for priority channel
 * @return None
 */
static inline void ADC_REG_SetPriorityChAwdEn(ADC_Type* regBase, adc_priority_channel_t channel, bool enable)
{
    regBase->PSQR[channel] = (regBase->PSQR[channel] & ~ADC_PSQR0_AWDEN_Msk)
                             | ((uint32_t)enable << ADC_PSQR0_AWDEN_Pos);
}

/*!
 * @brief Enable/Disable adc priority channel analog watchdog event interrupt
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @param[in] enable
 *            - true: Enable analog watchdog event interrupt for priority channel
 *            - false: Disable analog watchdog event interrupt for priority channel
 * @return None
 */
static inline void ADC_REG_SetPriorityChAwdIntEn(ADC_Type* regBase, adc_priority_channel_t channel, bool enable)
{
    regBase->PSQR[channel] = (regBase->PSQR[channel] & ~ADC_PSQR0_AWDIE_Msk)
                             | ((uint32_t)enable << ADC_PSQR0_AWDIE_Pos);
}

/*!
 * @brief Enable/Disable adc end of priority channel conversion interrupt
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @param[in] enable
 *            - true: Enable adc end of priority channel conversion interrupt
 *            - false: Disable adc end of priority channel conversion interrupt
 * @return None
 */
static inline void ADC_REG_SetPriorityChEOCIntEn(ADC_Type* regBase, adc_priority_channel_t channel, bool enable)
{
    regBase->PSQR[channel] = (regBase->PSQR[channel] & ~ADC_PSQR0_EOCIE_Msk)
                             | ((uint32_t)enable << ADC_PSQR0_EOCIE_Pos);
}

/*!
 * @brief Enable/Disable adc priority channel analog watchdog trigger out to ICM
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @param[in] enable
 *            - true: Enable adc priority channel analog watchdog trigger out to ICM
 *            - false: Disable adc priority channel analog watchdog trigger out to ICM
 * @return None
 */
static inline void ADC_REG_SetPriorityChAwdTrigEn(ADC_Type* regBase, adc_priority_channel_t channel, bool enable)
{
    regBase->PSQR[channel] = (regBase->PSQR[channel] & ~ADC_PSQR0_AWDTRIGEN_Msk)
                             | ((uint32_t)enable << ADC_PSQR0_AWDTRIGEN_Pos);
}

/*!
 * @brief Get the conversion result for normal channel
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Normal channel
 * @return Conversion result
 */
static inline uint16_t ADC_REG_GetNormalChResult(ADC_Type* regBase, adc_normal_channel_t channel)
{
    uint32_t regValue = regBase->NDR[channel];

    regValue &= ADC_NDR0_NDATA_Msk;

    return (uint16_t)regValue;
}

/*!
 * @brief Get the conversion result for priority channel
 *
 * @param[in] regBase: The adc register base address
 * @param[in] channel: Priority channel
 * @return Conversion result
 */
static inline int16_t ADC_REG_GetPriorityChResult(ADC_Type* regBase, adc_priority_channel_t channel)
{
    uint32_t regValue = regBase->PDR[channel];

    return (int16_t)regValue;
}

/*!
 * @brief Set ADC sample timing
 *
 * @param[in] regBaseAddr: The adc register base address
 * @return None
 */
static inline void ADC_REG_SetSampleTiming(uint32_t regBaseAddr)
{
    uint32_t regValue = 0U;

    *(volatile uint32_t*)(0x4000000CUL) = 0xB2063001UL;
    regValue = *(volatile uint32_t*)(regBaseAddr + 0x300UL);
    regValue &= (~0x1C000UL);
    *(volatile uint32_t*)(regBaseAddr + 0x300UL) = regValue;
    *(volatile uint32_t*)(0x4000000CUL) = 0xB2063000UL;
}

#if defined(__cplusplus)
}
#endif

#endif /*ADC_REG_ACCESS_H*/

/*******EOF********************************************************************/


